-------------------------------------------------------------------------------
-- Design Name: hw3_top_tb.vhd
-- Author: Aaron Baxter
-- Design Overview: Test bench to excercise serial to parallel converter
-- Two diffferent messages are sent with a good parity and a bad parity
-- The second message is sent with even parity
-------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
 
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
 
ENTITY hw3_top_tb IS
END hw3_top_tb;
 
ARCHITECTURE behavior OF hw3_top_tb IS 
 
	 -- Component Declaration for the Unit Under Test (UUT)
 
	 COMPONENT hw3_top
	 PORT(
			clk : IN  std_logic;
			rst : IN  std_logic;
			data : IN  std_logic;
			gate : IN  std_logic;
			odd_parity : IN  std_logic;
			out_byte : OUT  std_logic_vector(7 downto 0);
			valid : OUT  std_logic;
			bad_parity : OUT  std_logic
		  );
	 END COMPONENT;
	 

	--Inputs
	signal clk : std_logic := '0';
	signal rst : std_logic := '0';
	signal data : std_logic := '0';
	signal gate : std_logic := '0';
	signal odd_parity : std_logic := '0';

 	--Outputs
	signal out_byte : std_logic_vector(7 downto 0);
	signal valid : std_logic;
	signal bad_parity : std_logic;

	-- Clock period definitions
	constant clk_period : time := 20 ns;
 
	signal in_data : std_logic_vector(8 downto 0) := (others => '0');
	signal i : integer;
	
BEGIN
 
	-- Instantiate the Unit Under Test (UUT)
	uut: hw3_top PORT MAP (
			 clk => clk,
			 rst => rst,
			 data => data,
			 gate => gate,
			 odd_parity => odd_parity,
			 out_byte => out_byte,
			 valid => valid,
			 bad_parity => bad_parity
		  );

	-- Clock process definitions
	clk_process :process
	begin
		clk <= '0';
		wait for clk_period/2;
		clk <= '1';
		wait for clk_period/2;
	end process;
 

	-- Stimulus process
	stim_proc: process
	begin		
		-- hold reset state for 100 ns.
		rst <= '1';
		wait for clk_period*1;
		rst <= '0';

		wait for clk_period*2;

		--odd parity, correct parity sent
		odd_parity <= '1';
		in_data <= "111101001";
		for i in in_data'left downto 0 loop
			wait until falling_edge(clk);
			gate <= '1';
			data <= in_data(i);
		end loop;		
		wait until falling_edge(clk);
		gate <= '0';
		data <= '0';
		
		assert in_data (8 downto 1) = out_byte
			report "ERROR, out_byte"
			severity error;
		assert '1' = valid
			report "ERROR, valid"
			severity error;
		assert '0' = bad_parity
			report "ERROR, bad_parity"
			severity error;	
		
		wait for clk_period*2;

		
		--odd parity, incorrect parity sent
		odd_parity <= '1';
		in_data <= "111101000";
		for i in in_data'left downto 0 loop
			wait until falling_edge(clk);
			gate <= '1';
			data <= in_data(i);
		end loop;		
		wait until falling_edge(clk);
		data <= '0';
		gate <= '0';

		assert in_data (8 downto 1) = out_byte
			report "ERROR, out_byte"
			severity error;
		assert '1' = valid
			report "ERROR, valid"
			severity error;
		assert '1' = bad_parity
			report "ERROR, bad_parity"
			severity error;	

		wait for clk_period*2;

		--even parity, correct parity sent
		odd_parity <= '0';
		in_data <= "101011001";
		for i in in_data'left downto 0 loop
			wait until falling_edge(clk);
			gate <= '1';
			data <= in_data(i);
		end loop;		
		wait until falling_edge(clk);
		data <= '0';
		gate <= '0';

		assert in_data (8 downto 1) = out_byte
			report "ERROR, out_byte"
			severity error;
		assert '1' = valid
			report "ERROR, valid"
			severity error;
		assert '0' = bad_parity
			report "ERROR, bad_parity"
			severity error;	

		
		wait for clk_period*2;

		--even parity, incorrect parity sent
		odd_parity <= '0';
		in_data <= "101011000";
		for i in in_data'left downto 0 loop
			wait until falling_edge(clk);
			gate <= '1';
			data <= in_data(i);
		end loop;		
		wait until falling_edge(clk);
		data <= '0';
		gate <= '0';

		assert in_data (8 downto 1) = out_byte
			report "ERROR, out_byte"
			severity error;
		assert '1' = valid
			report "ERROR, valid"
			severity error;
		assert '1' = bad_parity
			report "ERROR, bad_parity"
			severity error;	
		
		
		wait for clk_period*2;
		
		-- send a few more clocks at the end
		wait until falling_edge(clk);
		wait until falling_edge(clk);
		wait until falling_edge(clk);
		assert false
			report "End of testbench, no error"
			severity failure;
	end process;

END;



